home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d18
/
futils.arc
/
XWIN.DOC
< prev
next >
Wrap
Text File
|
1991-04-28
|
13KB
|
337 lines
********************************************************************
************************* XWIN by Rex Kerr *************************
************************ Copyright (C) 1989 ************************
********************************************************************
This is a unit designed to give simple windowing capabilities to
any program. It uses FWRITE, so it is very fast, but it also
causes snow on snowy CGAs. It also won't autodetect EGA or VGA
cards (another weakness of FWRITE). It should work with EGA or
VGA normally, but not with the large screen sizes. But it is very
fast, and it works well for most programs that need windowing.
XWIN is implemented using a circular doubly linked list. Therefore,
you can call up any window at any time. By the way, it uses the
standard DOS and CRT units as well as my FWRITE unit.
***
XWIN's window structure is declared like this:
type win_scrbuf = array[1..4000] of byte; { This stores the window }
winptr = ^winrec;
winrec = record
x,y,w,h : byte; { The borders of the window }
cx,cy : byte; { The position of the cursor }
id : byte; { Each window has a unique ID
number }
scrsize : word; { The memory taken by the window
buffer, in bytes }
wscreen : win_scrbuf; { This is where the
saved window goes }
up,dn : winptr; { Pointers to the windows after
and before this one }
setas : byte; { If bit 0 is on, there is a
border. If bit 1 is on, the
window is hidden. }
end;
The only visible variable in the XWIN unit is the "base" of the
window list. The current window is always one up from this.
var windowset : winptr;
***
GetWinVram(var Scrn : Win_ScrBuf; x,y,w,h : byte);
This takes care of saving the window. Scrn is assumed to be
exactly the same size as it takes to hold the window defined
in x,y,w,h. Since the other windowing routines call it themselves,
you will probably not need to use this.
***
PutWinVram(Scrn : Win_ScrBuf);
This puts the window back on the screen after it has been saved.
Once again, Scrn is assumed to be just the right size.
***
Bordermaker(a,b,c,d,e,f : byte) : string;
This turns bytes a,b,c,d,e,f into characters and places them in a
string. It is useful for making window borders with ASCII values
above 126 or below 32.
border1 := bordermaker(218,191,192,217,196,179);
{ Window with a single-line border }
border2 := bordermaker(201,187,200,188,205,186);
{ Window with a double-line border }
***
SetTextAttr(attr : byte);
This sets the current writing attribute for Turbo Pascal's Write
and WriteLn.
***
GetXY(var x,y : byte);
This calls TP5's WhereX and WhereY. It's just a time-saver.
Note: If you are using FBIOS, BiosGetXY is much faster.
***
CreateWindow(id : byte; x,y,w,h : byte; wattr,battr : byte;
st,border : string);
Wow! What does this do?
The borders of the window are x,y,w,h. Border is either an empty
string (for no border) or the 6 chars used in the border. This is
what the characters are used for:
#1 : top left corner #2: top right corner
#3 : bottom left corner #4: bottom right corner
#5 : horizontal lines #6: vertical lines
St is the string used for the "title" of the window. It is placed
centered in the top line of the border. If there is no border, st
is not used. Batr is the attribute used for the border, and Watr
is the attribute used for the main text. While we're at it, here's
a table showing the which values give which colors:
COLOR FOREGROUND BACKGROUND HI-INTENSITY FOREGROUND
Black 0 0 8 (Gray)
Blue 1 16 9 (Light blue)
Green 2 32 10 (Light green)
Cyan 3 48 11 (Light cyan)
Red 4 64 12 (Pink)
Magenta 5 80 13 (Light magenta)
Brown 6 96 14 (Yellow)
White 7 112 15 (Hi-intensity white)
To get the desire attribute, add the foreground color to the
background color. For example, to get white on a black background,
the attribute is 7. For pink on a magenta background, the
attribute is 92. To make the foreground characters blink, add 128
to the total.
And finally, ID is the window's unique identification number. You
use it in most of the other window routines. If you specify the ID
number of an already existing window, nothing will happen.
***
PutWinBorder(x,y,w,h : byte; St,Border : string; Batr : byte);
This just writes a window border to the screen without actually
creating a window. You can use it to change the border of the
current window (by overwriting the old one) or just to write a
window box to the screen. The inside of the box is not cleared.
Border is a string of the border characters as shown in
CreateWindow, and St is the string to write in the border. Batr
is the attribute to use.
***
FancyWinBorder(x,y,w,h:byte; St,St2,Border:string; Batr,Ttatr,Btatr:byte);
Sometimes you want a fancier border than CreateWindow will give you.
The window's border is not saved as the six border chars and the
string to write. Instead, it is just saved as it in shown on the
screen. So if you somehow get "bad" characters in the border,
they'll stay there. But you can also use it to overwrite the old
border with a new one.
x,y,w,h is the border of the window (the same as CreateWindow)
St is the string to write in the top line of the border
St2 is the string to write in the bottom line of the border
Ttatr is the attribute to use for St
Btatr is the attribute to use for St2
Batr is the attribute to use for the rest of the border.
Border is similar to but different from the one in CreateWindow.
This is what FancyWinBorder's characters are used for:
#1 : Top right corner #2 : Top left corner
#3 : Bottom right corner #4 : Bottom left corner
#5 : Top right horizontal #6 : Top left horizontal
#7 : Bottom right horizontal #8 : Bottom left horizontal
#9 : Top right vertical #10 : Top left vertical
#11 : Bottom right vertical #12 : Bottom left vertical
So you have greater control over what the border looks like.
If you call FancyWinBorder(1,1,10,6,'','','abcdefghijkl',7,7,7)
you will get:
aeeeeffffb
i j
i j
k l
k l
cgggghhhhd
***
UpdateWindows;
This updates the screen. You use it after you have called a
procedure or function that changes or removes the window, but
doesn't update the screen.
***
SaveWindow;
This saves the current window on the screen to memory. If you
have written to the top window since you got to it, you need to
call this before calling UpdateWindow. If you don't, the changes
will be erased. You do not need to call this before any other
procedures.
***
RemoveWindow(id : byte);
This removes the window (specified by ID) from the linked list. It
doesn't, however, do anything about the image on the screen. If you
specify an ID that is non-existant, nothing will happen. You can
check to see if a window exists or not using ExistWindow. You will
probably want to call UpdateScreen soon after you call this.
***
GotoWindow(id : byte);
This gets the specified window and puts it at the beginning of the
linked list and updates the screen. If a non-existant ID is called,
nothing will happen.
***
HideWindow(id : byte);
This sets the window to be hidden. It doesn't do anything about the
screen, so UpdateScreen has to be called for that. If you use
gotowindow to go to the hidden window, the window will unhide. Also,
if you use popwindow and end up at a hidden window, the window will
unhide itself.
***
PopWindow;
This removes the current window from the linked list and the screen.
The window behind the current window now becomes the current window.
***
PopManyWindows(num : byte);
If you want to pop more than one window, use this. It is much
faster than PopWindow for popping more than one window.
***
ExistWindow(id : byte) : boolean;
This returns true if a window with the specified ID exists.
Otherwise, it returns false.
***
Okay, that's everything. But I'd like to write one extra routine
here. With createwindow, one of the problems is that it's a bit
hard to find out which ID numbers are already existing. You could
call existwindow from 1 until you get a false, but if you have a lot
of windows, that could take a few extra lines of code and extra time
that you might not want wasted. So let's write a function that returns
the lowest unused ID.
function EmptyWindowID : byte;
var temptr : winptr; { We need a pointer to walk through the list }
i,j : byte; { Variables for storing the free ID }
begin
i := 0; j := 0; { Initialize the variables }
while (i <> 0) do { i gets set to the free ID #. It will }
begin { remain 0 until then. }
inc(j); { j is the counter for possible open windows }
temptr := windowset^.up; { temptr is pointing to the
current window }
while (temptr <> windowset) and (temptr^.id <> j) do
begin { If temptr's ID = j or temptr has cirled the list, STOP }
nptr := nptr^.up; { Go up to the next window }
end;
if nptr = windowset then i := j; { If temptr has circled, }
end; { that ID is free, so set i }
EmptyWindowID := i; { give the function the result }
end;
What this does is it circles through the linked list to see if
any of the windows have an ID of 1. If none do, i is set to one.
Otherwise, the same thing is done for 2 and 3 and 4 etc. until
a "free" ID is found. Then the function is set to the value of i
(the free ID number).
A XWIN window takes up 22 bytes of heap plus the amount of memory
required to save the window in memory. Here's a formula to calculate
that amount of memory:
mem_required := (window_width * window_height) * 2;
But you don't have to worry about calculating the memory; XWIN does
it for you. You may want to test the heap to make sure it has
enough memory before calling createwindow. Like this:
function enoughmemory(x,y,w,h : byte) : boolean;
var temp : word;
begin
temp := ((w - x) + 1) * ((h - y) + 1);
temp := (temp * 2) + 22;
if (maxavail >= temp) then enoughmemory := true
else enoughmemory := false;
end;
----------------end-of-author's-documentation---------------
Software Library Information:
This disk copy provided as a service of
The Public (Software) Library
We are not the authors of this program, nor are we associated
with the author in any way other than as a distributor of the
program in accordance with the author's terms of distribution.
Please direct shareware payments and specific questions about
this program to the author of the program, whose name appears
elsewhere in this documentation. If you have trouble getting
in touch with the author, we will do whatever we can to help
you with your questions. All programs have been tested and do
run. To report problems, please use the form that is in the
file PROBLEM.DOC on many of our disks or in other written for-
mat with screen printouts, if possible. The P(s)L cannot de-
bug programs over the telephone.
Disks in the P(s)L are updated monthly, so if you did not get
this disk directly from the P(s)L, you should be aware that
the files in this set may no longer be the current versions.
For a copy of the latest monthly software library newsletter
and a list of the 2,000+ disks in the library, call or write
The Public (Software) Library
P.O.Box 35705 - F
Houston, TX 77235-5705
(713) 665-7017